package test.generator.writer;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.List;

import test.configuration.ConfigFactory;
import test.domain.Roster;
import test.domain.User;
import test.domain.environment.Database;

public class DBWriter implements Writer {
	private String driverName;
	private String url;
	private String username;
	private String password;
	
	private String insertUser = "insert into ofUser values (?, ?, ?, ?, ?, ?, ?);";
	private String insertRoster = "insert into ofRoster values (?, ?, ?, ?, ?, ?, ?);";
	
	public enum DBType {
		mssql, mysql, oracle;
	}
	
	public DBWriter() {
		Database database = ConfigFactory.getConfiguration().getDatabase();
		this.url = this.createUrl(database.getType(), database.getIp(), database.getPort(), database.getName());
		this.driverName = database.getClassName();
		this.username = database.getUsername();
		this.password = database.getPassword();
	}

	@Override
	public void write(List<User> users) {
		Connection con = this.getConnection();
		PreparedStatement st = null;
		
		try {
			for (User user : users) {
				// Insert users
				st = con.prepareStatement(insertUser);
				st.setString(1, user.getUsername());
				st.setString(2, user.getPlainPassword());
				st.setString(3, user.getEncryptedPassword());
				st.setString(4, user.getName());
				st.setString(5, user.getEmail());
				st.setString(6, user.getCreationDate());
				st.setString(7, user.getModifiedDate());
				
				st.executeUpdate();
				
				// Insert roster
				for (Roster roster : user.getRosters()) {
					st = con.prepareStatement(insertRoster);
					st.setInt(1, roster.getId());
					st.setString(2, roster.getUsername());
					st.setString(3, roster.getJid());
					st.setInt(4, roster.getSub());
					st.setInt(5, roster.getAsk());
					st.setInt(6, roster.getRecv());
					st.setString(7, roster.getNick());
					
					st.executeUpdate();
				}
				
				System.out.println("inserted user.. name: " + user.getUsername());
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			this.closeConnection(con);
		}		
	}
	
	private Connection getConnection() {
		Connection con = null;
		
		try {
			Class.forName(this.driverName).newInstance();
			System.out.println("url: " + url);
			con = DriverManager.getConnection(url, username, password);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Error Trace in getConnection() : " + e.getMessage());
		}
		
		return con;
	}
	
	private String createUrl(String dbType, String dbIp, String dbPort, String dbName) {
		DBType type = DBType.valueOf(dbType);
		String url;
		
		switch(type) {
			case mssql:
				url = "jdbc:sqlserver://" + dbIp + ":" + dbPort + ";databaseName=" + dbName;
				break;
			case mysql:
				url = "jdbc:mysql://" + dbIp + ":" + dbPort + "/" + dbName;
				break;
			default:
				throw new UnsupportedOperationException("Not supported database type.");
		}
		
		return url;
	}
	
	private void closeConnection(Connection con) {
		try {
			if (con != null) {
				con.close();
				con = null;
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
